/**
*******************************************************
*@file  adc.c 
*@brief adc.c
*@author 花满楼
*@date     2020-7-1
*@version  V1
*@attention none
*******************************************************
*/
#include "adc.h"
#include "delay.h"

ADC_HandleTypeDef ADC3_Handler;/**<ADC句柄*/

u16 ADC_DMA_ConvertedValue[8];	//ADC转换数组
u16 temperter[8];   /**<ADC信号采集的中间变量*/

/** 
*******************************************************
*@brief 初始化ADC
*@param   none
*@return  none
*@note    none
*******************************************************
*/
void ADC3_Init(void)
{
    ADC_ChannelConfTypeDef ADC3_ChanConf;
    ADC3_Handler.Instance = ADC3;
    ADC3_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频，ADCCLK=PCLK2/4=90/4=22.5MHZ
    ADC3_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式
    ADC3_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐
    ADC3_Handler.Init.ScanConvMode = ENABLE;                    //开启扫描模式
    ADC3_Handler.Init.EOCSelection = DISABLE;                    //关闭EOC中断
    ADC3_Handler.Init.ContinuousConvMode = DISABLE;              //关闭连续转换   如果将 CONT 位置 1，规则通道转换不会在组中最后一个所选通道处停止，而是再 次从第一个所选通道继续转换
    ADC3_Handler.Init.NbrOfConversion = 7;                       //2个转换在规则序列中 也就是只转换规则序列2
    ADC3_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式
    ADC3_Handler.Init.NbrOfDiscConversion = 0;                   //不连续采样通道数为0
    ADC3_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发
    ADC3_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
    ADC3_Handler.Init.DMAContinuousRequests = ENABLE;           //开启DMA请求
    HAL_ADC_Init(&ADC3_Handler);                                 //初始化
    
    ADC3_ChanConf.Channel = ADC_CHANNEL_14;
    ADC3_ChanConf.SamplingTime = ADC_SAMPLETIME_112CYCLES;      //采样时间
    ADC3_ChanConf.Offset = 0;
    ADC3_ChanConf.Rank = 1;                                     //第1个序列，序列1  通道1
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       //通道配置
    
    ADC3_ChanConf.Channel = ADC_CHANNEL_15;                     //通道15
    ADC3_ChanConf.Rank = 2;                                     //第1个序列，序列2
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       
    ADC3_ChanConf.Channel = ADC_CHANNEL_4;                      //通道4
    ADC3_ChanConf.Rank = 3;                                     //第1个序列，序列3
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       
    ADC3_ChanConf.Channel = ADC_CHANNEL_5;                      //通道5
    ADC3_ChanConf.Rank = 4;                                     //第1个序列，序列4
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       
    ADC3_ChanConf.Channel = ADC_CHANNEL_6;                      //通道6
    ADC3_ChanConf.Rank = 5;                                     //第1个序列，序列5
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       //通道配置
    ADC3_ChanConf.Channel = ADC_CHANNEL_7;                      //通道7
    ADC3_ChanConf.Rank = 6;                                     //第1个序列，序列6
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       
    ADC3_ChanConf.Channel = ADC_CHANNEL_8;                      //通道8
    ADC3_ChanConf.Rank = 7;                                     //第1个序列，序列7
    HAL_ADC_ConfigChannel(&ADC3_Handler, &ADC3_ChanConf);       
}

/** 
*******************************************************
*@brief ADC底层驱动，引脚配置，时钟使能
*@param   hadc:ADC句柄
*@return  none
*@note    此函数会被HAL_ADC_Init()调用
*******************************************************
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC3_CLK_ENABLE();            //使能ADC3时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();           //开启GPIOF时钟
    GPIO_Initure.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;    
    GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟
    GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉
    HAL_GPIO_Init(GPIOF, &GPIO_Initure);
}

/** 
*******************************************************
*@brief 获取指定通道的转换值，取times次,然后平均
*@param[in]   times:获取次数
*@param[out]  temp：通道ch的times次转换结果平均值
*@return  none
*@note    none
*******************************************************
*/
void Get_Adc_Average(u16 *temp, u8 times)
{
    u32 temp_val[8] = {0};
    u8 t;

    for (t = 0; t < times; t++)
    {
        HAL_ADC_Start(&ADC3_Handler);                               //开启ADC
        delay_ms(5);
        temp_val[0] += ADC_DMA_ConvertedValue[0];
        temp_val[1] += ADC_DMA_ConvertedValue[1];
        temp_val[2] += ADC_DMA_ConvertedValue[2];
        temp_val[3] += ADC_DMA_ConvertedValue[3];
        temp_val[4] += ADC_DMA_ConvertedValue[4];
        temp_val[5] += ADC_DMA_ConvertedValue[5];
        temp_val[6] += ADC_DMA_ConvertedValue[6];
    }

    for (t = 0; t < 7; t++)
    {
        temp[t] = temp_val[t] / times;
        temp[t] = (float) temp[t] * 3300 / 4096;   //获取计算后的带小数的实际电压值，比如3111.1mV
        temp_val[t] = 0;
    }
}

/** 
*******************************************************
*@brief 获取ADC的采样数据
*@param[in]   none
*@param[out]  none
*@return  none
*******************************************************
*/
void ADC_Samp()
{
    Get_Adc_Average(temperter, 5);      //读取电压采样数据
}
